package bufmgr;

import chainexception.ChainException;
import diskmgr.*;
import java.util.*;
import global.*;

class bufDesc {};

public class BufMgr {
	byte bufpool[][];
	bufDesc[] descriptors;
	Hashtable directory;
	String policy;

	public BufMgr(int numbufs, String replacerArg){
		bufpool = new byte[numbufs][GlobalConst.MINIBASE_BUFFER_POOL_SIZE];		// each buffer is of size MINIBASE_BUFFER_POOL_SIZE bytes
		descriptors = new bufDesc[numbufs];
		directory = new Hashtable();
		policy = replacerArg;
	}

	public void pinPage(PageId pin_pgid, Page page, boolean emptyPage) throws ChainException {
	/*
	When a pin request is received, the BP manager needs an efficient way to determine whether the page is already in the buffer pool. To handle this, you should implement a simple hash table, or map. With an input of page_number, the hash table should return the frame_number that the page occupies (or "nil" if the page is not present). Of course, this hash table should be main-memory based. Yes, you may use available Java classes (java.utils) for this.
	*/
		boolean is_page_replacement_candidate = true;

		if (directory.contains (new Integer(pin_pgid))) {
			int which_frame = (Integer)directory.get(pin_pgid);
			// which_frame is the buf. no.
			// modify its descriptor
			if (descriptors[which_frame] == 0)
				is_page_replacement_candidate = false;
			descriptors[which_frame].pin_count++;

			// what to return, doc says pointer to page, use Page ctor
			page = Page (bufpool[which_frame]);
		}
		else {
			// pick a policy replaced page, if ditry -writepage- else remove
			int get_evicted_frame = some_func();
			
			//1- un-pin it 
			//2- remove from hashtable
			directory.remove(get_evicted_frame);
			//3- write back
			if (descriptors[get_evicted_frame].dirtybit == 1)
				flushPage (pin_pgid);	// is it ok?

			// 4- write new page to slot created  and pin it


			
		}

			// what to do
		//throw new ChainException();
	}

	public void unpinPage(PageId PageId_in_a_DB, boolean dirty) throws ChainException{
		throw new ChainException();
	}

	public PageId newPage(Page firstpage, int howmany){
		return new PageId();
	}

	public void freePage(PageId globalPageId) throws ChainException{
		throw new ChainException();
	}

	public void flushPage(PageId pageid){
		
	}

	public int getNumUnpinnedBuffers(){
		return 0;
	}

	public int getNumBuffers() {
		return 0;
	}
}

class bufDesc {
	/* The pin_count field is an integer, page_number is a PageId object, and dirtybit is a boolean. This describes the page that is stored in the corresponding frame. A page is identified by a page_number that is generated by the DB class when the page is allocated, and is unique over all pages in the database. The PageId type is defined as an integer type.
	*/

	public:
		PageId page_number;
		int pin_count;
		boolean dirtybit;
	
	public bufDesc (PageId x, int pc, boolean d) {
		page_number = x;
		pin_count = pc;
		dirtybit = d;
	}

//	public void modify_pc (int newpc) {
//		pin_count = newpc;
//	}

}
